﻿using Furion.DynamicApiController;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using BaseNet.Application.System.Role.Dto;
using BaseNet.Core.Consts;
using BaseNet.Core.Dtos;
using BaseNet.Core.SeedData;
using BaseNet.Core.SeedData.Dto;
using BaseNet.Core.Utils;
using BaseNet.Entity.System;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace BaseNet.Application.System.Role
{
    /// <summary>
    /// 系统角色接口实现
    /// </summary>
    [ApiDescriptionSettings(Module = ModuleConsts.System)]
    [SecurityDefine(SecurityConsts.System_Role)]
    public class RoleService : IDynamicApiController
    {
        private readonly SqlSugarClient _db;
        public RoleService(ISqlSugarRepository sqlSugarRepository)
        {
            _db = sqlSugarRepository.Context;
        }

        /// <summary>
        /// 添加系统角色
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task Add(SysRoleAddInput input)
        {
            using (var mutex = new Mutex(true, "/api/system/role/add/"))
            {
                try
                {
                    if (!mutex.WaitOne(0, true))//若存在接口堵塞，则直接退出
                        throw Oops.Oh("当前接口存在正在进行的访问");

                    if (_db.Queryable<SysRoleEntity>().Where(o => o.Name == input.Name.Trim()).Any())
                        throw new Exception("角色名称重复");

                    var entity = input.Adapt<SysRoleEntity>();

                    await _db.ExtInsertableAsync(entity);
                }
                finally
                {
                    try
                    {
                        mutex.ReleaseMutex();
                    }
                    catch (Exception) { }
                    mutex.Close();
                    mutex.Dispose();
                }
            }
        }

        /// <summary>
        /// 修改系统角色
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task Edit(SysRoleEditInput input)
        {
            using (var mutex = new Mutex(true, "/api/system/role/edit/" + input.Id))
            {
                try
                {
                    if (!mutex.WaitOne(0, true))//若存在接口堵塞，则直接退出
                        throw Oops.Oh("当前接口存在正在进行的访问");

                    if (_db.Queryable<SysRoleEntity>().Where(o => o.Id != input.Id).Where(o => o.Name == input.Name.Trim()).Any())
                        throw new Exception("角色名称重复");

                    var entity = await _db.Queryable<SysRoleEntity>()
                        .Where(o => o.Id == input.Id)
                        .FirstAsync();
                    if (entity == null)
                        throw new Exception("当前角色不存在");

                    entity.Name = input.Name;
                    entity.IsActive = input.IsActive;
                    entity.Sort = input.Sort;

                    await _db.ExtUpdateableAsync(entity);
                }
                finally
                {
                    try
                    {
                        mutex.ReleaseMutex();
                    }
                    catch (Exception) { }
                    mutex.Close();
                    mutex.Dispose();
                }
            }
        }

        /// <summary>
        /// 删除系统角色
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task Del(PrivateEntityBase input)
        {
            using (var mutex = new Mutex(true, "/api/system/role/del/" + input.Id))
            {
                try
                {
                    if (!mutex.WaitOne(0, true))//若存在接口堵塞，则直接退出
                        throw Oops.Oh("当前接口存在正在进行的访问");

                    //1.系统角色数据
                    var entity = await _db.Queryable<SysRoleEntity>()
                        .Where(o => o.Id == input.Id)
                        .FirstAsync();
                    if (entity == null)
                        throw new Exception("当前角色不存在");

                    //2.系统角色与菜单关联表
                    var sysRoleMenuList = await _db.Queryable<SysRoleMenuEntity>()
                        .Where(o => o.RoleId == input.Id)
                        .ToListAsync();
                    //3.用户与系统角色关联表
                    var sysUserRoleList = await _db.Queryable<SysUserRoleEntity>()
                        .Where(o => o.RoleId == input.Id)
                        .ToListAsync();

                    await _db.UseTranAsync(async () =>
                    {
                        await _db.ExtDeleteableAsync(entity);
                        await _db.ExtDeleteableAsync(sysRoleMenuList);
                        await _db.ExtDeleteableAsync(sysUserRoleList);
                    }, o => throw Oops.Oh(o.Message));
                }
                finally
                {
                    try
                    {
                        mutex.ReleaseMutex();
                    }
                    catch (Exception) { }
                    mutex.Close();
                    mutex.Dispose();
                }
            }
        }

        /// <summary>
        /// 设置角色有效性
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task SetActive(PrivateEntityBase input)
        {
            using (var mutex = new Mutex(true, "/api/system/role/setactive/" + input.Id))
            {
                try
                {
                    if (!mutex.WaitOne(0, true))//若存在接口堵塞，则直接退出
                        throw Oops.Oh("当前接口存在正在进行的访问");

                    var entity = await _db.Queryable<SysRoleEntity>()
                        .Where(o => o.Id == input.Id)
                        .FirstAsync();
                    if (entity == null)
                        throw new Exception("当前角色不存在");

                    entity.IsActive = !entity.IsActive;

                    await _db.ExtUpdateableAsync(entity);
                }
                finally
                {
                    try
                    {
                        mutex.ReleaseMutex();
                    }
                    catch (Exception) { }
                    mutex.Close();
                    mutex.Dispose();
                }
            }
        }

        /// <summary>
        /// 设置角色权限
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task SetRolePermission(SysRolePermissionInput input)
        {
            using (var mutex = new Mutex(true, "/api/system/role/setrolepermission/" + input.Id))
            {
                try
                {
                    if (!mutex.WaitOne(0, true))//若存在接口堵塞，则直接退出
                        throw Oops.Oh("当前接口存在正在进行的访问");

                    //1.移除原本的角色菜单关联表数据
                    var oldSysRoleMenuList = await _db.Queryable<SysRoleMenuEntity>()
                        .Where(o => o.RoleId == input.Id)
                        .ToListAsync();

                    //2.添加新的角色菜单关联数据
                    var newSysRoleMenuList = input.MenuIds.Select(o => new SysRoleMenuEntity
                    {
                        RoleId = input.Id,
                        MenuId = o
                    }).ToList();

                    //3.移除原本的角色权限关联表数据
                    var oldSysRoleSecurityList = await _db.Queryable<SysRoleSecurityEntity>()
                        .Where(o => o.RoleId == input.Id)
                        .ToListAsync();

                    //4.添加新的角色权限关联表
                    var newSysRoleSecurityList = input.SecurityList.Select(o => new SysRoleSecurityEntity
                    {
                        RoleId = input.Id,
                        Security = o
                    }).ToList();

                    await _db.UseTranAsync(async () =>
                    {
                        await _db.ExtDeleteableAsync(oldSysRoleMenuList);
                        await _db.ExtInsertableAsync(newSysRoleMenuList);
                        await _db.ExtDeleteableAsync(oldSysRoleSecurityList);
                        await _db.ExtInsertableAsync(newSysRoleSecurityList);
                    }, o => throw Oops.Oh(o.Message));
                }
                finally
                {
                    try
                    {
                        mutex.ReleaseMutex();
                    }
                    catch (Exception) { }
                    mutex.Close();
                    mutex.Dispose();
                }
            }
        }

        /// <summary>
        /// 获取角色权限
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<SysRolePermissionOutput> GetRolePermission(PrivateEntityBase input)
        {
            var result = new SysRolePermissionOutput();

            //返回前，排除父级菜单
            var parentMenuIds = SysMenuSeedData.GetTreeList(SysMenuSeedData.GetList()).FindAll(o => o.Children.Count > 0).Select(o => o.Id).Distinct();
            result.MenuIds = await _db.Queryable<SysRoleMenuEntity>()
                .Where(o => o.RoleId == input.Id)
                .Where(o => !parentMenuIds.Contains(o.MenuId))
                .Select(o => o.MenuId)
                .ToListAsync();
            result.SecurityList = await _db.Queryable<SysRoleSecurityEntity>()
                .Where(o => o.RoleId == input.Id)
                .Select(o => o.Security)
                .ToListAsync();
            var menuList = SysMenuSeedData.GetList();
            var menuList2 = menuList.Select(o => new LayuiTreeDto
            {
                Id = o.Id,
                Title = o.Title,
                Spread = true,
                Checked = false,
                Disabled = false,
                PId = o.PId,
            }).ToList();
            var treeList = LayuiTreeDto.BuildLayUiTreeList(menuList2);
            result.AllMenuTreeList = treeList;

            result.AllSecurityTreeList = SecuritySeedData.GetList().Select(o => new LayuiTreeDto
            {
                Id = o,
                Title = o,
                Spread = true,
                Checked = false,
                Disabled = false,
            }).ToList();

            return result;
        }

        /// <summary>
        /// 获取角色列表
        /// </summary>
        /// <returns></returns>
        public async Task<List<SysRoleDto>> GetList()
        {
            var list = await _db.Queryable<SysRoleEntity>()
                .OrderBy(o => o.Sort)
                .Select<SysRoleDto>()
                .ToListAsync();

            return list;
        }

        /// <summary>
        /// 获取角色详情
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<SysRoleDto> GetInfo(PrivateEntityBase input)
        {
            var dto = await _db.Queryable<SysRoleEntity>()
                .Select<SysRoleDto>()
                .FirstAsync(o => o.Id == input.Id);

            return dto;
        }

    }
}
